from __future__ import annotations

"""
应用配置（基于 Pydantic Settings）
---------------------------------
职责：
- 从环境变量/`.env` 读取运行参数（端口、数据库、JWT、外部服务等）
- 提供便捷属性将逗号分隔的字符串转换为列表
- 使用 `lru_cache` 缓存配置实例，避免重复解析

注意：
- 生产环境请通过环境变量覆盖默认值；不要将机密写入仓库
- `timezone` 默认为 Asia/Shanghai，影响日志/业务逻辑中的时间语义
"""

from functools import lru_cache
from typing import List, Optional

from pydantic import AnyHttpUrl, Field
from pydantic_settings import BaseSettings, SettingsConfigDict


class Settings(BaseSettings):
    port: int = Field(8080, env="PORT")
    database_url: str = Field(
        "postgresql+psycopg://app:app@postgres:5433/app", env="DATABASE_URL"
    )

    jwt_secret: str = Field("ChangeMe_JWT_Secret_123", env="JWT_SECRET")
    jwt_access_minutes: int = Field(30, env="JWT_ACCESS_MIN")
    jwt_refresh_days: int = Field(14, env="JWT_REFRESH_DAYS")

    timezone: str = Field("Asia/Shanghai", env="TIMEZONE")

    hb_base_url: AnyHttpUrl = Field("http://hbapi:8000", env="HB_BASE_URL")
    hb_basic_user: str = Field("admin", env="HB_BASIC_USER")
    hb_basic_pass: str = Field("admin", env="HB_BASIC_PASS")

    allowed_connectors: str = Field(
        "gate_io_perpetual,okx_perpetual",
        env="ALLOWED_CONNECTORS",
    )
    allowed_symbols: str = Field(
        "ETH-USDT,BTC-USDT",
        env="ALLOWED_SYMBOLS",
    )
    allowed_order_types: str = Field(
        "MARKET,LIMIT",
        env="ALLOWED_ORDER_TYPES",
    )
    webhook_rate_per_min: int = Field(60, env="WEBHOOK_RATE_PER_MIN")
    user_rate_per_min: int = Field(120, env="USER_RATE_PER_MIN")
    max_notional_default: float = Field(1000, env="MAX_NOTIONAL_DEFAULT")
    slippage_bps_limit: int = Field(50, env="SLIPPAGE_BPS_LIMIT")
    slippage_guard_enabled: bool = Field(False, env="SLIPPAGE_GUARD_ENABLED")

    worker_concurrency: int = Field(2, env="WORKER_CONCURRENCY")

    rsshub_enabled: bool = Field(False, env="RSSHUB_ENABLED")
    rsshub_base_url: str = Field("http://rsshub:1200", env="RSSHUB_BASE_URL")
    rsshub_feeds: str = Field("", env="RSSHUB_FEEDS")
    rsshub_poll_interval: int = Field(300, env="RSSHUB_POLL_INTERVAL")
    rsshub_request_timeout: int = Field(10, env="RSSHUB_REQUEST_TIMEOUT")
    rsshub_items_per_fetch: int = Field(50, env="RSSHUB_ITEMS_PER_FETCH")

    admin_seed_email: str = Field("admin@example.com", env="ADMIN_SEED_EMAIL")
    admin_seed_password: str = Field("Admin@1234", env="ADMIN_SEED_PASSWORD")
    admin_seed_enabled: bool = Field(True, env="ADMIN_SEED_ENABLED")

    default_account_prefix: str = Field("acct", env="DEFAULT_ACCOUNT_PREFIX")

    two_factor_enabled: bool = Field(False, env="TWO_FACTOR_ENABLED")
    two_factor_issuer: str = Field("TVAutoTrading", env="TWO_FACTOR_ISSUER")
    two_factor_static_code: str = Field("000000", env="TWO_FACTOR_STATIC_CODE")

    docs_enabled: bool = Field(True, env="DOCS_ENABLED")
    docs_url: Optional[str] = Field("/docs", env="DOCS_URL")
    redoc_url: Optional[str] = Field("/redoc", env="REDOC_URL")
    openapi_url_path: Optional[str] = Field("/internal/openapi.json", env="OPENAPI_URL")

    deepseek_api_key: Optional[str] = Field(None, env="DEEPSEEK_API_KEY")
    deepseek_base_url: str = Field("https://api.deepseek.com", env="DEEPSEEK_BASE_URL")
    deepseek_model: str = Field("deepseek-reasoner", env="DEEPSEEK_MODEL")

    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
        extra="ignore",
    )

    @staticmethod
    def _split(value: str | List[str]) -> List[str]:
        """将逗号分隔字符串拆分为去空白的字符串列表。"""
        if isinstance(value, list):
            return value
        return [item.strip() for item in value.split(",") if item.strip()]

    @property
    def allowed_connectors_list(self) -> List[str]:
        return self._split(self.allowed_connectors)

    @property
    def allowed_symbols_list(self) -> List[str]:
        return self._split(self.allowed_symbols)

    @property
    def allowed_order_types_list(self) -> List[str]:
        return self._split(self.allowed_order_types)

    @staticmethod
    def _split_pairs(value: str) -> List[str]:
        if not value:
            return []
        return [item.strip() for item in value.split(";") if item.strip()]

    @property
    def rsshub_feed_list(self) -> List[tuple[str, str]]:
        feeds: List[tuple[str, str]] = []
        for chunk in self._split_pairs(self.rsshub_feeds):
            if "|" in chunk:
                name, path = chunk.split("|", 1)
            else:
                name, path = chunk, chunk
            name = name.strip()
            path = path.strip()
            if not path:
                continue
            feeds.append((name or path, path))
        return feeds


@lru_cache()
def get_settings() -> Settings:
    """获取全局单例配置对象。"""
    return Settings()
